<?php

namespace app\index\controller;

use AlibabaCloud\SDK\Dingtalk\Vyida_1_0\Models\GetRunningTasksResponseBody\result;
use app\admin\common\Constants;
use app\admin\model\WechatMessage;
use think\Controller;
use think\Db;
use think\Loader;
use think\Queue;
use think\Request;
use think\Validate;

class Dingding extends Controller
{
    private $accessKey = 'suite3od943cv881vgrqh';                                             // 第三方应用的Suitekey
    private $token = 'nYypyTi31eJbiidx6XfOelKz9XbLNqz';                                       // 钉钉开放平台上，开发者设置的token
    private $encodingAesKey = 'sUNMOzCJnjFeAldOFll5OmYgFzq3Xejin8Lx64NGK8h';                  // 钉钉开放台上，开发者设置的EncodingAESKey
    private $suiteSecret = 'Z2I-3UXoEKpuvw7ystmlrkEvy3_k00IBlOxuxGUpFzuFi7FZpGUiZTVDMl7QdeUI';// 三方应用秘钥
    private $corpid = 'dingb1ffb7a5066d11e6acaaa37764f94726';                                 // 授权方的CorpId；小程序使用dd.corpId获取到的和这个值一致

    /**
     * 钉钉回调请求地址
     * */
    public function notice()
    {
        $input = Request()->param();

        $msg_signature = $input['msg_signature'];
        $timestamp = $input['timestamp'];
        $nonce = $input['nonce'];
        $encrypt = $input['encrypt'];

        Loader::import('dingtalk\DingCallbackCrypto', EXTEND_PATH);
        $crypt = new \DingCallbackCrypto($this->token, $this->encodingAesKey, $this->accessKey);
        $text = $crypt->getDecryptMsg($msg_signature, $timestamp, $nonce, $encrypt);

        $text_arr = json_decode($text, true);
        $biz_type = $text_arr['bizData'][0]['biz_type'];
        if ($biz_type == 2) {
            file_put_contents(RUNTIME_PATH . 'dingding_text.txt', $text);
        } else if ($biz_type == 4) {
            file_put_contents(RUNTIME_PATH . 'dingding_drop_text.txt', $text);
        }

        return $crypt->getEncryptedMap("success");
    }

    /**
     * 钉钉获取userid
     * */
    public function ddLogin()
    {
        $input = Request()->param();

        $code = $input['code'];

        if (empty($code)) apiReturn(2, '免登授权码缺失');

        $url = 'https://oapi.dingtalk.com/topapi/v2/user/getuserinfo';

        $access_token = $this->getAccessToken();

        $url = $url . '?access_token=' . $access_token;
        $data = [
            'code' => $code
        ];

        $header[] = 'content-type: application/json';
        $json = httpsRequest($url, json_encode($data), $header);
        $result = json_decode($json, true);

        if ($result['errcode'] == 0) {
            $info = [
                'userid' => $result['result']['userid'],
                'unionid' => $result['result']['unionid']
            ];

            apiReturn(1, '获取数据成功', $info);
        } else {
            apiReturn(2, '获取用户信息失败');
        }
    }


    /**
     * 获取SuiteTicket
     * */
    public function getSuiteTicket()
    {
        $dd_notice = file_get_contents(RUNTIME_PATH . 'dingding_text.txt');
        $dd_notice = json_decode($dd_notice, true);

        $biz_data = json_decode($dd_notice['bizData'][0]['biz_data'], true);
        $suiteTicket = $biz_data['suiteTicket'];

        return $suiteTicket ? : '';
    }

    /**
     * 获取签名
     * */
    public function getSign($millisecond)
    {
        $suiteTicket = $this->getSuiteTicket();                                           // 钉钉给应用推送的ticket，测试应用随意填写如：TestSuiteTicket，正式应用需要从推送回调获取suiteTicket。
        $suiteSecret = $this->suiteSecret;                                                // 三方应用秘钥
        $signStr = $millisecond . "\n" . $suiteTicket;
        $hmac_sha256_str = base64_encode(hash_hmac("sha256", $signStr, $suiteSecret, true));

        $signature = urlencode($hmac_sha256_str);

        return $signature;
    }


    /**
     * 服务商获取第三方应用授权企业的access_token
     * 文档地址：https://open.dingtalk.com/document/isvapp-server/obtains-the-enterprise-authorized-credential
     * */
    public function getAccessToken()
    {
        $json = file_get_contents(RUNTIME_PATH . 'dd_access_token.json');
        $result = json_decode($json, true);

        if (!$result || !$result['access_token'] || $result['expires_time'] <= time()) {
            $url = 'https://oapi.dingtalk.com/service/get_corp_token';
            $accessKey = $this->accessKey;
            $timestamp = getMillisecond();
            $suiteTicket = $this->getSuiteTicket();
            $signature = $this->getSign($timestamp);
            $auth_corpid = $this->corpid;

            $data = [
                'accessKey' => $accessKey,
                'timestamp' => $timestamp,
                'suiteTicket' => $suiteTicket,
                'signature' => $signature,
                'auth_corpid' => $auth_corpid
            ];

            $url = $url . '?accessKey=' . $accessKey . '&timestamp=' . $timestamp . '&suiteTicket=' . $suiteTicket . '&signature=' . $signature . '&auth_corpid=' . $auth_corpid;

            $header[] = 'content-type: application/json';
            $json = httpsRequest($url, json_encode($data), $header);
            $result = json_decode($json, true);
            if ($result['errcode'] == 0) {
                $result['expires_time'] = time() + $result['expires_in'] - 60;

                file_put_contents(RUNTIME_PATH . 'dd_access_token.json', json_encode($result));
            } else {
                return false;
            }
        }
        return $result['access_token'];
    }

    public function getAuthCorpId()
    {
        $json = file_get_contents(RUNTIME_PATH . 'dingding_drop_text.txt');

        return json_decode($json, true)['bizData'][0]['corp_id'];
    }

    /**
     * 获取第三方应用授权企业的accessToken
     * 文档地址：https://open.dingtalk.com/document/isvapp-server/obtain-the-access_token-of-the-authorized-enterprise
     * */
    public function getDropAccessToken()
    {
        $json = file_get_contents(RUNTIME_PATH . 'dd_drop_access_token.json');
        $result = json_decode($json, true);

        if (!$result || !$result['access_token'] || $result['expires_time'] <= time()) {
            $url = 'https://api.dingtalk.com/v1.0/oauth2/corpAccessToken';
            $accessKey = $this->accessKey;
            $suiteSecret = $this->suiteSecret;
            $auth_cropid = $this->getAuthCorpId();
            $suiteTicket = $this->getSuiteTicket();

            $data = [
                'suiteKey' => $accessKey,
                'suiteSecret' => $suiteSecret,
                'authCorpId' => $auth_cropid,
                'suiteTicket' => $suiteTicket
            ];

            $header[] = 'content-type: application/json';
            $json = httpsRequest($url, json_encode($data), $header);
            $result = json_decode($json, true);
            if ($result['errcode'] == 0) {
                $result['expires_time'] = time() + $result['expires_in'] - 60;

                file_put_contents(RUNTIME_PATH . 'dd_drop_access_token.json', json_encode($result));
            } else {
                return false;
            }
        }
        return $result['access_token'];
    }

    /**
     * 获取agent_id
     * */
    public function getAgentId()
    {
        $url = 'https://oapi.dingtalk.com/service/get_auth_info';

        $accessKey = $this->accessKey;
        $timestamp = getMillisecond();
        $suiteTicket = $this->getSuiteTicket();
        $signature = $this->getSign($timestamp);

        $suite_key = $this->accessKey;
        $auth_corpid = $this->corpid;

        $url = $url . '?accessKey=' . $accessKey . '&timestamp=' . $timestamp . '&suiteTicket=' . $suiteTicket . '&signature=' . $signature;
        $data = [
            'suite_key' => $suite_key,
            'auth_corpid' => $auth_corpid
        ];

        $header[] = 'content-type: application/json';
        $json = httpsRequest($url, json_encode($data), $header);
        $result = json_decode($json, true);

        return $result['auth_info']['agent'][0]['agentid'];
    }

    /**
     * 获取spaceId
     * */
    public function getSpaceId()
    {
        $access_token = $this->getAccessToken();
        if ($access_token === false) apiReturn(2, '获取access_token失败');

        $domain = 'aaa';
        $agent_id = $this->getAgentId();

        $url = 'https://oapi.dingtalk.com/cspace/get_custom_space?access_token=' . $access_token . '&domain=' . $domain . '&agent_id=' . $agent_id;
        $info = file_get_contents($url);
        $info = json_decode($info, true);

        if ($info['errcode'] == 0) {
            apiReturn(1, '获取数据成功', $info['spaceid']);
        } else {
            apiReturn(2, $info['errmsg']);
        }
    }

    public function test()
    {
        echo $this->getSpaceId();exit;
        $this->previewAuth('01383139693021813601', 'GDJE0gDQnpupZggPhrvtQAiEiE');
    }

    /**
     * 给某用户授权spaceid
     * */
    public function authorityToUser()
    {
        $input = Request()->param();

        $user_id = $input['user_id'];

        if(empty($user_id)) apiReturn(2,'用户ID缺失');

        $dd_userid = Db::name('user')->where(['id' => $user_id])->value('dd_userid');
        if(empty($dd_userid)) apiReturn(2,'请前往【我的】绑定钉钉');

        $url = 'https://oapi.dingtalk.com/cspace/grant_custom_space?';

        $param = [
            'access_token' => $this->getAccessToken(),
            'agent_id' => $this->getAgentId(),
            'domain' => 'aaa',
            'type' => 'add',
            'userid' => $dd_userid,
            'path' => '/'
        ];

        $url = $url . http_build_query($param);
        $res = file_get_contents($url);
        if($res){
            apiReturn(1, '成功');
        }else{
            apiReturn(2, '权限不足');
        }
    }

    /**
     * 预览授权
     * */
    public function previewAuth($user_id, $unionId)
    {
        $url = "https://api.dingtalk.com/v1.0/drive/spaces/{$this->getSpaceId()}/files/customSpacePrivileges?x-acs-dingtalk-access-token=" . $this->getAccessToken();

        $header[] = 'Content-Type:application/json';

        $data = [
            'type' => 'preview',
            'userId' => $user_id,
            'fileIds' => [0],
            'duration' => 3000,
            'unionId' => $unionId
        ];

        $res = httpsRequest($url, json_encode($data), $header);
        echo "<pre>";
        print_r($res);
        exit;
    }


    //更新dd_userid && dd_unionid
    public function saveDdUserInfo()
    {
        $input = Request()->param();

        $uid = $input['uid'];
        $userid = $input['userid'];
        $unionid = $input['unionid'];

        if (empty($uid)) apiReturn(2, '用户ID不能为空');
        if (empty($userid)) apiReturn(2, 'userid不能为空');

        $res = Db('user')->where(['id' => $uid])->update(['dd_unionid' => $unionid, 'dd_userid' => $userid]);

        if ($res) {
            apiReturn(1, '成功');
        } else {
            apiReturn(2, '失败');
        }
    }

    //解绑钉钉
    public function unbind()
    {
        $input = Request()->param();

        $uid = $input['uid'];

        if (empty($uid)) apiReturn(2, '会员ID不能为空');

        $res = Db('user')->where(['id' => $uid])->update(['dd_userid' => '', 'dd_unionid' => '']);
        if ($res) {
            apiReturn(1, '成功');
        } else {
            apiReturn(2, '失败');
        }
    }

    //提交申请
    public function submit_application()
    {
        $input = Request()->param();

        $uid = $input['uid'];                   //用户ID也就是申请人ID
        $lng = $input['lng'];
        $lat = $input['lat'];
        $seal_id = $input['seal_id'];          //印章ID
        $app_id = $input['app_id'];            //审批类型ID
        $name = $input['name'];                //文件名称
        $number = $input['number'];            //文件编号
        $frequency = $input['frequency'];      //用章次数
        $company_id = $input['company_id'];
        $imgs = $input['imgs'];                 //图片
        $remark = $input['remark'];             //备注
        $dd_file = $input['dd_file'];           //申请文档 我觉得上传到本地了，是个地址
        $uuid = $input['uuid'];

        if (!is_numeric($uid)) apiReturn(2, '申请人ID为空或者格式错误');
        if (!$lng || !$lat) apiReturn(2, '请打开小程序定位');
        if (!is_numeric($seal_id)) apiReturn(2, '印章ID不能为空或者格式错误');
        if (!$app_id) apiReturn(2, '审批类型不能为空或者格式错误');
        if (!is_numeric($app_id)) apiReturn(2, '审批类型不能为空或者格式错误');
        if(empty($imgs)) apiReturn(2,'请上传图片');
        if (!$name) apiReturn(2, '文件名称不能为空');
        if (!is_numeric($frequency)) apiReturn(2, '用章次数不能为空或者格式错误');

        $time = time();

        $data = [
            'uid' => $uid,                   //用户ID也就是申请人ID
            'lng' => $lng,
            'lat' => $lat,
            'seal_id' => $seal_id,          //印章ID
            'app_id' => $app_id,            //审批类型ID
            'name' => $name,                //文件名称
            'number' => $number,            //文件编号
            'frequency' => $frequency,      //用章次数
            'remaining_times' => $frequency,//剩余次数就是用章次数，不过要等审核通过之后才会有用
            'company_id' => $company_id,
            'imgs' => $imgs,                 //图片
            'remark' => $remark,             //备注
            'dd_file' => $dd_file,           //申请文档 我觉得上传到本地了，是个地址
        ];

        $data['create_time'] = time();

        //审批流程
        $is_free = Db('approval')->where(['id' => $app_id])->value('is_free');
        if ($is_free == 2 && !$uuid) apiReturn(2, '审批人不能为空');

        $res = Db('app_form')->insertGetId($data);
        if ($res) {
            //提交成功我就添加审核流程
            //审批类型ID

            if ($is_free == 2) {
                //是自由审批流程
                $u_list = explode(',', $uuid);
                foreach ($u_list as $k => $v) {
                    $add_data['uid'] = $v;
                    $add_data['form_id'] = $res;
                    $add_data['create_time'] = $time;
                    $add_data['company_id'] = $company_id;
                    if ($k == 0) {
                        //轮到他审批，第一个人是当前审批人
                        $add_data['status'] = 1;
                    } else {
                        $add_data['status'] = 4;
                    }
                    Db('approval_process')->insertGetId($add_data);
                }
            } else {
                $app_list = Db('approver')->where(['app_id' => $app_id])->order('sort asc')->select();
                foreach ($app_list as $k => $v) {
                    $add_data['uid'] = $v['uid'];
                    $add_data['form_id'] = $res;
                    $add_data['create_time'] = $time;
                    $add_data['company_id'] = $company_id;
                    if ($k == 0) {
                        // 发送模板消息（用章申请提醒）
                        $user_id = Db('user')->where(['id' => $v['uid']])->value('dd_userid');

                        if ($user_id) {
                            // 申请人
                            $apply_username = Db('user')->where(['id' => $uid])->value('username');
                            // 申请部门
                            $department_id = Db('staff')->where(['uid' => $uid])->value('department_id');
                            $list = explode(',', $department_id);
                            $d_id = $list[0];
                            $partment_name = Db('department')->where(['id' => $d_id])->value('name');

                            // 公章名称
                            $seal_id = Db('app_form')->where(['id' => $res])->value('seal_id');
                            $seal_type = Db('seal')->where(['id' => $seal_id])->value('seal_type');
                            $configModel = new \app\admin\model\Config();
                            $type_list_res = $configModel->getConfigCacheByName(Constants::$SEAL_TYPE_KEY);
                            $type_list = array_merge($type_list_res);
                            if ($seal_type == 1) {
                                $type_name = $type_list[0]['name'];
                            } elseif ($seal_type == 2) {
                                $type_name = $type_list[1]['name'];
                            } elseif ($seal_type == 3) {
                                $type_name = $type_list[2]['name'];
                            } elseif ($seal_type == 4) {
                                $type_name = $type_list[3]['name'];
                            }

                            // 文件名称
                            $name = Db('app_form')->where(['id' => $res])->value('name');

                            $date = date('Y-m-d H:i:s');

                            $data = [
                                'apply_user' => $apply_username,
                                'apply_department' => $partment_name,
                                'time' => $date,
                                'seal_name' => $type_name,
                                'use_count' => $frequency,
                                'text_name' => $name,
                            ];
                            sendDDMsg($this->getAccessToken(), $this->getAgentId(), 'a774190a8b4f431cb3844b562031f017', $user_id, json_encode($data, JSON_UNESCAPED_UNICODE));
                        }

                        //轮到他审批，第一个人是当前审批人
                        $add_data['status'] = 1;
                    } else {
                        $add_data['status'] = 4;
                    }
                    Db('approval_process')->insert($add_data);
                }
            }
            apiReturn(1, '成功', $res);
        } else {
            apiReturn(2, '失败');
        }
    }

    public function to_examine()
    {
        $input = Request()->param();

        $form_id = $input['form_id'];//申请表单ID
        $uid = $input['uid'];        //审批人ID
        $state = $input['state'];    //state 1:同意 2：拒绝
        $remark = $input['remark'];
        $remark_content = $input['remark_content'];

        if (!$form_id) apiReturn(2, '表单ID为空');
        if (!$uid) apiReturn(2, '审批人ID为空');
        if (!$state) apiReturn(2, '操作类型为空');

        //可能提交了几次，找到最大的那条记录ID
        $mid = Db('approval_process')->where(['form_id' => $form_id, 'uid' => $uid])->order('id desc')->value('id');
        if ($state == 1) {
            //同意 同意的话还要看后面的有没有人，审批流程有没有结束
            Db('approval_process')->where(['id' => $mid])->update(['status' => 2, 'app_time' => time()]);

            $id_list = Db('approval_process')->where(['form_id' => $form_id])->order('id asc')->field('id')->select();
            $max_ids = max($id_list);
            $max_id = $max_ids['id'];
            $ids = array_column($id_list, 'id');
            //当前ID的下标值
            $key = array_search($mid, $ids);
            //看最大值大于$id不，大于就代表后面还有审批人
            if ($max_id > $mid) {
                $next_id = $id_list[$key + 1]['id'];
                //轮到下一个人审核 status:1为当前审核人
                Db('approval_process')->where(['id' => $next_id])->update(['status' => 1]);


                //openid:审核人的app_openid   $uid 申请人的uid  $res  表单ID
                $sh_uid = Db('approval_process')->where(['id' => $next_id])->value('uid');

                $form_id = Db('approval_process')->where(['id' => $next_id])->value('form_id');
                $sq_uid = Db('app_form')->where(['id' => $form_id])->value('uid');

                //发送模板消息（用章申请提醒）
                $user_id = Db('user')->where(['id' => $sh_uid])->value('dd_userid');
                if ($user_id) {
                    // 申请人
                    $apply_username = Db('user')->where(['id' => $sq_uid])->value('username');
                    // 申请部门
                    $department_id = Db('staff')->where(['uid' => $sq_uid])->value('department_id');
                    $list = explode(',', $department_id);
                    $d_id = $list[0];
                    $partment_name = Db('department')->where(['id' => $d_id])->value('name');

                    // 公章名称
                    $seal_id = Db('app_form')->where(['id' => $form_id])->value('seal_id');
                    $seal_type = Db('seal')->where(['id' => $seal_id])->value('seal_type');
                    $configModel = new \app\admin\model\Config();
                    $res = $configModel->getConfigCacheByName(Constants::$SEAL_TYPE_KEY);
                    $type_list = array_merge($res);
                    if ($seal_type == 1) {
                        $type_name = $type_list[0]['name'];
                    } elseif ($seal_type == 2) {
                        $type_name = $type_list[1]['name'];
                    } elseif ($seal_type == 3) {
                        $type_name = $type_list[2]['name'];
                    } elseif ($seal_type == 4) {
                        $type_name = $type_list[3]['name'];
                    }

                    $form_info = Db('app_form')->field('name,frequency')->where(['id' => $form_id])->find();
                    $name = $form_info['name'];
                    $frequency = $form_info['frequency'];

                    $date = date('Y-m-d H:i:s');

                    $data = [
                        'apply_user' => $apply_username,
                        'apply_department' => $partment_name,
                        'time' => $date,
                        'seal_name' => $type_name,
                        'use_count' => $frequency,
                        'text_name' => $name,
                    ];
                    sendDDMsg($this->getAccessToken(), $this->getAgentId(), 'a774190a8b4f431cb3844b562031f017', $user_id, json_encode($data, JSON_UNESCAPED_UNICODE));
                }
            } else {
                //审批流程走完了
                Db('approval_process')->where(['form_id' => $form_id])->update(['form_state' => 1]);
                Db('app_form')->where(['id' => $form_id])->update(['status' => 4]);
                //走完了，要发送通知给申请人
                //openid:申请人的app_openid   $uid 申请人的uid  $res  表单ID

                //发送模板消息（用章申请完成提醒）
                $uid = Db('app_form')->where(['id' => $form_id])->value('uid');
                $user_id = Db('user')->where(['id' => $uid])->value('dd_userid');

                if ($user_id) {
                    // 申请事项
                    $form_name = Db('app_form')->where(['id' => $form_id])->value('name');

                    // 申请人
                    $username = Db('user')->where(['id' => $uid])->value('username');

                    $date = date('Y-m-d H:i:s');

                    $data = [
                        'item' => $form_name,
                        'user' => $username,
                        'time' => $date,
                        'result' => '通过'
                    ];
                    sendDDMsg($this->getAccessToken(), $this->getAgentId(), '3d2f553aad6c4799988cdabee05ae9bf', $user_id, json_encode($data, JSON_UNESCAPED_UNICODE));
                }
            }
        } elseif ($state == 2) {
            //要写拒绝原因
            if (!$remark_content) {
                $remark_content = '';
            } else {
                $remark = 4;
            }
            Db('app_form')->where(['id' => $form_id])->update(['status' => 3]);
            Db('approval_process')->where(['id' => $mid])->update(['status' => 3, 'remark' => $remark, 'remark_content' => $remark_content, 'app_time' => time()]);
        }
        apiReturn(1, '成功');
    }

    public function useSealImg()
    {
        $input = Request()->param();

        $id = $input['id'];
        $imgs = $input['imgs'];
        $dd_used_file = $input['dd_used_file'];

        if (!$id) apiReturn(2, '表单ID为空');
        if (!$imgs) apiReturn(2, '图片不能为空');

        $res = Db::name('app_form')->where(['id' => $id])->update(['used_img' => $imgs, 'dd_used_file' => $dd_used_file, 'update_time' => time()]);
        if ($res) {
            //上传图片完成，就要改变表单状态
            Db::name('approval_process')->where(['form_id' => $id])->setField('form_state', 2);
            file_put_contents(RUNTIME_PATH . 'sql.txt', Db::name('approval_process')->getLastSql());

            $params['form_id'] = $id;
            $time = 60 * 60 * 24;
            $params['status'] = 1;//1是上传图片 24小时之后变状态   2：是判断24小时之后有没有上传图片去锁定用户
            Queue::later($time, Constants::$DELAY_QUEUE['handler'], $params, Constants::$DELAY_QUEUE['queue']);

            apiReturn(1, '成功');
        } else {
            apiReturn(2, '失败');
        }
    }

    /**
     * OCR获取图片文字信息
     * */
    public function getOcrInfo()
    {
        $input = Request()->param();

        $img_url = $input['img_url'];

        if (empty($img_url)) apiReturn(2, '图片地址不能为空');

        $url = "https://api.topthink.com/ocr/txt?";
        $param = [
            'appCode' => '93fa836c339c921493f626c2ee784906',
            'imgurl' => $img_url
        ];

        $url = $url . http_build_query($param);

        $info = json_decode(file_get_contents($url), true);
        if ($info['code'] == 0) {
            apiReturn(1, '图片识别成功', $info['data'][0]['texts']);
        } else {
            apiReturn(2, '图片识别失败');
        }
    }
}
